/***********************************************************************
 * Module:  Dame.java
 * Author:  nabil
 * Purpose: Defines the Class Dame
 ***********************************************************************/
package model.jeu_de_dame;
import model.util.Couleur;
import model.gestion_mouvement.FactoryMouvementDame;
import model.gestion_mouvement.MouvementValidator;
import java.util.*;
import model.gestion_mouvement.IPiece;

/**
 * <b>Dame représente une piece particuliere du jeu de dame. Elle étend Piece.
 * </b>
 * @see Damier
 * @see Piece
 * @author nabil mansouri
 * @version 2.0
 */
public class Dame extends Piece {
    
              /**
         * Constructeur Dame.
         * <p>
         * Initialisation de la dame avec les coordonnées de la case x et y. Cette méthode affecte
         * la couleur au pion et une référence vers le Damier.
         * </p>
         * @param monDamier 
         *           la référence vers le damier auquel elle appartient
         *@param  x
         *           la position x du pion 
         *@param  y
         *           la position y du pion 
         *@param  couleur
         *           la couleur du pion   
         *  
         */
    public Dame(Damier monDamier,int x, int y,Couleur couleur)
    {
        super(monDamier,x,y,couleur);
        
    }
  
                 /**
         * Constructeur Dame.
         * <p>
         * Initialisation de la dame à partir des caractéristique d'une autre piece.
         * </p>
         * @param p
         *        la piece qui que l'on va utiliser pour instancier notre dame. 
         *  
         */
    public Dame(Piece p)
    {//on cree une dame à partir d une piece quelquonque généralement un pion
        this(p.getDamier(),p.getPositionX(),p.getPositionY(),p.getCouleur());
    }
   
  /**Retourne la liste des cases accessible par la dame
     * @return Retourne la liste des cases accessible par la dame
     */
    public ArrayList<Case> getCasesAccessibles()
    {
       ArrayList<Case> lesCases = new ArrayList<Case>();
       ArrayList<ArrayList<Case>> lesChemins = this.getCase().getMesVoisines();
       boolean peutManger = false;
            for(ArrayList<Case> chemin : lesChemins)
            {
               ListIterator iter = (ListIterator)chemin.listIterator();
                   Case courante = null;
                   boolean continuerChemin = true;
                   if(peutManger)
                       continuerChemin=false;
                   while(iter.hasNext() && continuerChemin)
                   {
                       courante = (Case)iter.next();
                       //si la case courante contien un ennemi ainsi que la precedente alors on a deux pieces consecutifs=>return false
                       if(courante.hasPiece() && courante.getPiece().isEnnemie(this))
                       {//si il y a une case precedente et cette case comporte un ennemi aussi=>return false
                           if(iter.hasNext())//normalement le precedent est le courant
                           {//on recupere le precedente la case "courante"
                              int indexSuivant = iter.nextIndex();          
                              Case suivante = chemin.get(indexSuivant);
                              if(!suivante.hasPiece())
                              {
                                    if(!peutManger)
                                        lesCases.clear();
                                    lesCases.add(suivante);
                                    peutManger = true;
                              }
                              else
                                  continuerChemin = false;
                           }//si on a un ami sur la route on peut sortir de ce chemin
                            else if(courante.hasPiece() && courante.getPiece().isAmie(this))
                           {
                               continuerChemin = false;
                           }                   
                       }
                       else if(!courante.hasPiece())
                           lesCases.add(courante);
                       else if(courante.getPiece().isAmie(this))
                           continuerChemin = false;
                       
                  }
            }
            return lesCases;
    }

   /**Retourne si la dame peut manger ou non. Dans cette méthode, les diagonales accessibles
     * par la dame seront parcourus. Si il existe une piece ennemie sur le chemin qu'il est 
     * possible de manger, alors la méthode renvoie true. La méthode respect les règles du jeu de dame.
     * @return true si la dame peut manger false sinon
     */
    public boolean peutManger()
    {
            ArrayList<ArrayList<Case>> lesChemins = this.getCase().getMesVoisines();
            for(ArrayList<Case> chemin : lesChemins)
            {
               ListIterator iter = (ListIterator)chemin.listIterator();
                   Case courante = null;
                   boolean continuerChemin = true;
                   while(iter.hasNext() && continuerChemin)
                   {
                       courante = (Case)iter.next();
                       //si la case courante contien un ennemi ainsi que la precedente alors on a deux pieces consecutifs=>return false
                       if(courante.hasPiece() && courante.getPiece().isEnnemie(this))
                       {//si il y a une case precedente et cette case comporte un ennemi aussi=>return false
                           if(iter.hasNext())//normalement le precedent est le courant
                           {//on recupere le precedente la case "courante"
                              int indexSuivant = iter.nextIndex();          
                              Case suivante = chemin.get(indexSuivant);
                              if(!suivante.hasPiece())
                                    return true;
                              else
                                  continuerChemin = false;
                           }//si on a un ami sur la route on peut sortir de ce chemin
                            else if(courante.hasPiece() && courante.getPiece().isAmie(this))
                           {
                               continuerChemin = false;
                           }                   
                       }
                        
                  }
            }
            return false;
    }
    
    /**Retourne si la dame peut se déplacer ou non. Dans cette méthode, le chemin
     * est parcourus. Les regles suivantes sont respectées:
     * <ul><li>La case d'arrivé est vide</li>
     * <li>La case d'arrivé doit exister</li>
     * <li>La case doit être autorisé</li>
     * <li>Il ne doit pas y avoir deux pieces consécutives sur le chemin</li>
     * <li>Il ne doit pas y avoir de pieces amie sur le chemin</li></ul>
     * @return true si la dame s'est déplacé false sinon
     */
    public boolean seDeplacer(Case arrive)
    {
        FactoryMouvementDame fact = FactoryMouvementDame.getInstance();
        MouvementValidator valid = fact.createValidateur();
        valid.setArrive(arrive);
        valid.setDepart(this.getCase());
        valid.setCouleur(couleur);
        if(valid.isValid())
        {
           this.aManger = valid.peutManger();
           for(IPiece p : valid.getPieceAManger())
           {
               this.manger((Piece)p);
           }
           this.effectuerDeplacement(arrive);
           return true;
       }
       return false;
    }
    
     public boolean peutBouger()
     {
         return !this.getCasesAccessibles().isEmpty();
     }

    @Override
    public ArrayList<Case> getCheminOffensif() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public ArrayList<Case> getPlusSurChemins() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    
}